package com.gugee.ins.common.dal.service.blogger.impl;

import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gugee.ins.common.constant.GugeeInsExceptionConst;
import com.gugee.ins.common.constant.RedisKeyConst;
import com.gugee.ins.common.dal.mapper.blogger.InsBloggerExtMapper;
import com.gugee.ins.common.dal.service.blogger.InsBloggerDao;
import com.gugee.ins.common.dto.InsBloggerFollowerDto;
import com.gugee.ins.common.model.ai.InComeResponse;
import com.gugee.ins.common.model.ai.InsBloggerCategory;
import com.gugee.ins.common.model.ai.InsBloggerLanguage;
import com.gugee.ins.common.model.mysql.blogger.InsBlogger;
import com.gugee.ins.common.model.spider.blogger.InsBloggerUserFromId;
import com.gugee.ins.data.common.msg.InsBloggerMessage;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * insBlogger dao
 * @author Huangxin
 */
@Slf4j
@Service
public class InsBloggerDaoImpl extends ServiceImpl<InsBloggerExtMapper,InsBlogger> implements InsBloggerDao {
    @Override
    public long getMaxId() {
        return baseMapper.getMaxId();
    }
    @Override
    public List<InsBloggerMessage> findInsBloggerMessageByPages(long startId, long endId) {
        return baseMapper.findInsBloggerMessageByPagesId(startId,endId);
    }
    @Override
    public List<InsBloggerMessage> findInsBloggerMessageByPages(long startId, long endId,long followerCount,long lastCollectTime) {
        return baseMapper.findInsBloggerMessageByPages(startId,endId,followerCount,lastCollectTime);
    }
    @Override
    public List<InsBloggerMessage> findInsMBloggerFromInsBlogger(long startId, long endId,long followerCount) {
        return baseMapper.findInsMBloggerFromInsBlogger(startId,endId,followerCount);
    }

    /**
     * insBlogger 优先采集 redis key 的过期时间
     */
    @NacosValue(value="${ins.data.collector.insBloggerCollect.priority.redis.out:180}", autoRefreshed = true)
    int insBloggerPriorityCollectRedisOutOfTime;

    /**
     * redis
     */
    @Autowired
    RedisTemplate<String,String> redisTemplate;

    /**
     * 批量收录
     * @param insBloggerMessageList
     * @return
     */
    @Override
    public void batchInsert(List<InsBloggerMessage> insBloggerMessageList){
        long nowTime = System.currentTimeMillis() / 1000;
        try{
            baseMapper.batchInsert(insBloggerMessageList,nowTime);
        }catch (Exception e){
            e.printStackTrace();
            log.debug("batch insert ins blogger collect failed ,try insert one by one, msg : {} ",e.getMessage());
            insBloggerMessageList.forEach(insBloggerMessage -> {
                try{
                    baseMapper.insertOne(insBloggerMessage,nowTime);
                }catch (Exception ex){
                    e.printStackTrace();
                    log.info("ins blogger collect failed ,uid : {} ,username : {}, msg : {} "
                            ,insBloggerMessage.getUid(),insBloggerMessage.getUserName(),ex.getMessage());
                }
            });
        }
    }

    /**
     * 判断是否需要采集
     * @param uid
     * @param needSearchDba 是否需要查询数据库
     * @return
     */
    @Override
    public boolean checkCollecting(long uid,boolean needSearchDba) {
        //todo 这里后续可能需要进行修改，队列数据多了以后redis内存会剧增
        //查询redis是否正在被采集
        if(!StringUtils.isEmpty(redisTemplate.opsForValue().get(RedisKeyConst.INS_BLOGGER_COLLECTING + uid))){
            return false;
        }

        if(needSearchDba && baseMapper.findByUid(uid) != null){
            //查询数据库是否已存在
            return false;
        }

        //再次查询redis是否正在被采集
        Boolean isExist = redisTemplate.opsForValue().setIfAbsent(RedisKeyConst.INS_BLOGGER_COLLECTING + uid,
                (System.currentTimeMillis() / 1000) + "", insBloggerPriorityCollectRedisOutOfTime, TimeUnit.MINUTES);
        if(isExist != null && !isExist){
            return false;
        }

        return true;
    }

    /**
     * 根据uid查找数据
     * @param uid
     * @return
     */
    @Override
    public InsBlogger findByUid(long uid){
        return baseMapper.findByUid(uid);
    }

    /**
     * 查询存在的uid
     * @param uids
     * @return
     */
    @Override
    public List<InsBlogger> findExistUidByUids(List<Long> uids){
        return baseMapper.findExistUidByUids(uids);
    }

    @Override
    public List<Long> findExistUidByUidsWithCollectTime(@Param("uids") List<Long> uids, long collectTime){
        if(uids.isEmpty()){
            return new ArrayList<>();
        }
        return baseMapper.findExistUidByUidsWithCollectTime(uids,collectTime);
    }

    /**
     * 根据条件获取真实粉丝或僵尸粉丝列表
     * @return
     */
    @Override
    public List<InsBlogger> findByFollower(long uid, boolean isZombie){
        return baseMapper.findByFollower(uid,isZombie);
    }

    @Override
    public long countByFollower(long uid,boolean isZombie){
        return baseMapper.countByFollower(uid,isZombie);
    }

    /**
     * 根据 帖子 shortcode 查找标记用户及其账户类型
     * @param shortcode
     * @return
     */
    @Override
    public List<InsBloggerMessage> findInsBloggerByShortcode(String shortcode){
        return baseMapper.findInsBloggerByShortcode(shortcode);
    }


    @Override
    public int updateBlogger(InsBloggerUserFromId insBloggerUserFromId) {

        if(insBloggerUserFromId==null ||insBloggerUserFromId.getIsPrivate()==null){
            throw GugeeInsExceptionConst.BIZ_UID_IS_NULL_BLOGGER_MAIN;
        }
        insBloggerUserFromId.setLastCollectTime(System.currentTimeMillis() / 1000);
        return  baseMapper.updateByPrimaryKeySelective(insBloggerUserFromId);

    }

    /**
     * 根据uid条件更新
     * @param insBlogger 数据
     * @return
     */
    @Override
    public void updateByUidSelective(InsBlogger insBlogger){
        UpdateWrapper<InsBlogger> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("uid",insBlogger.getUid());
        baseMapper.update(insBlogger,updateWrapper);
    }

    /**
     * 根据uid 更新年龄和性别
     * @param age
     * @param gender
     * @param birth
     * @param race
     * @param uid
     */
    @Override
    public void updateAiGenderAndAiAgeByUid(int age,int gender,int birth,String race,long uid){
        baseMapper.updateAiGenderAndAiAgeByUid(age,gender,birth,race,uid,System.currentTimeMillis() / 1000);
    }

    /**
     * 根据uid 更新国家
     * @param uid
     * @param nation
     * @param nationSource
     */
    @Override
    public void updateNation(long uid,String nation,int nationSource){
        baseMapper.updateNation(uid,nation,nationSource,System.currentTimeMillis() / 1000);
    }

    /**
     * 根据uid 更新语言
     * @param uid
     * @param language
     */
    @Override
    public void updateLanguage(long uid,String language){
        baseMapper.updateLanguage(uid,language,System.currentTimeMillis() / 1000);
    }

    /**
     * 批量更新 语言
     * @param insBloggerLanguages
     */
    @Override
    public void batchUpdateLanguage(List<InsBloggerLanguage> insBloggerLanguages){
        long now = System.currentTimeMillis() / 1000;
        try{
            baseMapper.batchUpdateLanguage(insBloggerLanguages,now);
        }catch (Exception e){
            log.debug("batch Update ins blogger  Analysis Language failed ,try Update one by one, msg : {} ",e.getMessage());
            insBloggerLanguages.forEach(insBloggerLanguage -> {
                try{
                    baseMapper.updateLanguage(insBloggerLanguage.getUid(),insBloggerLanguage.getLanguage(),now);
                }catch (Exception ex){
                    log.info("Update ins blogger  Analysis Language failed ,uid : {},language : {} , msg : {} "
                            ,insBloggerLanguage.getUid(),insBloggerLanguage.getLanguage(),ex.getMessage());
                }
            });
        }
    }

    /**
     * 根据uids 更新 近30天粉丝增长数和粉丝增长率
     * @param uids
     */
    @Override
    public void updateLastFollowerGrowByUids(List<Long> uids){
        baseMapper.updateLastFollowerGrowByUids(uids);
    }

    /**
     * 根据uid条件更新
     * @param insBlogger 数据
     * @return
     */
    @Override
    public void updateByUid(InsBlogger insBlogger){
        baseMapper.updateByUid(insBlogger);
    }

    /**
     * 更新关注人列表采集时间
     * @param uid
     */
    @Override
    public void updateFollowingCollectTime(long uid) {
        baseMapper.updateFollowingCollectTime(uid,System.currentTimeMillis() / 1000);
    }

    /**
     * 更新真实粉丝占比率
     * @param uid
     * @param realFollowerRate
     */
    @Override
    public void updateRealFollowerRate(long uid,double realFollowerRate){
        baseMapper.updateRealFollowerRate(uid,realFollowerRate);
    }

    /**
     * 批量更新ai收入
     * @param inComeResponses
     */
    @Override
    public void batchUpdateIncome(List<InComeResponse> inComeResponses){
        baseMapper.batchUpdateIncome(inComeResponses,System.currentTimeMillis() / 1000);
    }

    /**
     * 批量更新ai分类
     * @param insBloggerCategories
     */
    @Override
    public void batchUpdateAiCategory(List<InsBloggerCategory> insBloggerCategories) {
        baseMapper.batchUpdateAiCategory(insBloggerCategories);
    }

    /**
     * 更新状态
     * @param uid
     * @param status
     */
    @Override
    public void updateAccountStatus(long uid ,int status) {
        baseMapper.updateAccountStatus(uid,status);
    }

    /**
     * 根据uid获取粉丝数等信息
     * @param uids
     * @return
     */
    @Override
    public List<InsBloggerFollowerDto> findFollowerCountByUid(List<Long> uids) {
        return baseMapper.findFollowerCountByUid(uids);
    }
}
